/*
This file is part of Docking@Home.
http://docking.gcl.cis.udel.edu
Copyright (C) 2009 University of Delaware

Docking@Home is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Docking@Home is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Docking@Home.  If not, see <http://www.gnu.org/licenses/>.
*/
/*
	Filename: BioModel.h
	Description: A abstract class that will contain all information and 
		functions for any biological model 
	Revision History: 
		Created - 01/14/08
	Author: Robert Keller (01/14/08 -> Current)
*/

#ifndef _BioModel_h
#define _BioModel_h

#include <vector>

using std::vector;

#include "../GLHelper.h"
#include "../ArcBall.h"
#include "Atom.h"
#include "Bond.h"
#include "DrawRep.h"

#include <sys/stat.h>

#define BIOMODEL_MAX_FILNAME_LENGTH 50

class BioModel
{
public:

	// Destructor 

	virtual ~BioModel();

	// Public Member Modifiers

	void setPDBFilename (
		const char filename[BIOMODEL_MAX_FILNAME_LENGTH]);
	void setPSFFilename (
		const char filename[BIOMODEL_MAX_FILNAME_LENGTH]);

	// Public Member Accessors
	
	ArcBallT * getArcBall ();

	unsigned int getNumAtoms ();
	unsigned int getNumBonds ();

	// Public File Reading Functions

	bool readFile();

	// Rotation Functions
	void addUserRotation (float deg);
	void subtractUserRotation (float deg);

	// Draw Representation Functions
	DrawRep getDrawRep ();
	float getDistanceBetweenFromDrawRep ();
	void setDrawRep (DrawRep rep);

	// No Atoms Rendering Functions
	void drawNoAtomsText (float winWidth, float winHeight);

	// Gets the number of atoms in the molecule
	inline size_t GetAtoms(){return this->atoms.size();}
	// Gets the number of bonds in the molecule
	inline size_t GetBonds(){return this->bonds.size();}
	// Gets the centroid of the molecule
	inline void GetCentroid(float centroid[3]){memcpy(&centroid[0],&this->Center[0],sizeof(float)*3);}
	// Sets the centroid of the molecule
	inline void SetCentroid(const float centroid[3]){memcpy(&this->Center[0],&centroid[0],sizeof(float)*3);}

	// Functions that all Biological Models need to implement
	virtual void draw () = 0;
	virtual void drawMultiple (bool useThisTransformation) = 0;

	// View Changing Functions

	virtual void addToTranslateX () = 0;
	virtual void addToTranslateY () = 0;
	virtual void addToTranslateZ () = 0;

	virtual void subtractFromTranslateX () = 0;
	virtual void subtractFromTranslateY () = 0;
	virtual void subtractFromTranslateZ () = 0;

protected:

	// Constructor 

	BioModel ();

	// Protected Member Modifiers

	void setMaxEner (float ener);
	void setRmsd (float newRmsd);
	void setSeed (float newSeed);

	// Member Accessors

	Atom getAtom (unsigned int index);
	Bond getBond (unsigned int index);

	float getMaxEner () const;
	float getRMSD () const;
	float getSeed () const;

	// Atom / Bond Addition Functions

	void addAtom (Atom a);
	void addBond (Bond b);

	// Protected File Reading Functions

	void readPDB(char pdbFilename [BIOMODEL_MAX_FILNAME_LENGTH]);
	void readPSF(char psfFilename [BIOMODEL_MAX_FILNAME_LENGTH]);

	// Rendering Representations

	void drawVDWRep ();
	void drawVDWRep (float distanceBetween);
	
	void drawLineRep ();
	void drawLineRep (float distanceBetween);
	
	void drawCPKRep ();
	void drawCPKRep (float distanceBetween);

	// Rendering Helper Functions

	void performModelTransformations (float distanceBetween, float angle, float trans[3], float arcTransformation[16] );

	void calculateModelCenter(float modelCenter[3]);
	void calculateCenteringTranslation(float centering[3], float modelCenter[3], float distanceBetween);

	float Center[3];

	// Model Information Variables

	vector<Atom> atoms;
	vector<Bond> bonds;

	float maxEner; // Energy of molecule
	float rmsd;	// rmsd value
	float seed; // seed id

	// Rendering Variables

	static GLHelper * glHelper;

	// Draw Representation
	DrawRep drawRep;

	// ArcBall for display
	ArcBallT arcBall;

	// Translation Variables

	float translateX;
	float translateY;
	float translateZ;

	// Rotation Variables
	float userRotation; // in degrees
	float modelRotation; // in degrees (from psf or pdb file)
	float modelRotationAxis[3]; // (from psf or pdb file)

	// Filenames

	char pdbFilename[BIOMODEL_MAX_FILNAME_LENGTH];
	char psfFilename[BIOMODEL_MAX_FILNAME_LENGTH];

	// Last Modified Time
	
	struct stat  pdbLastModified;
	struct stat  psfLastModified;

	// Positioning Constants

	const float DEFAULT_LINE_LENGTH;
	const float DEFAULT_CPK_LENGTH;
	const float DEFAULT_VDW_LENGTH;
	const float DEFAULT_MULTIPLE_LENGTH;
	const float DEFAULT_CPK_ATOM_SIZE;

};

#endif
